package com.sense.kukoo.common.wiget.adapter;

import android.view.LayoutInflater;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;


import com.sense.kukoo.common.wiget.adapter.loadmore.BaseLoadMoreView;
import com.sense.kukoo.common.wiget.adapter.loadmore.ILoadMore;
import com.sense.kukoo.common.wiget.adapter.loadmore.LoadMoreStatus;
import com.sense.kukoo.common.wiget.adapter.viewholder.BaseViewHolder;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;

public abstract class BaseAdapter<T> extends RecyclerView.Adapter<BaseViewHolder> {
    public final static int LOADMORE_VIEW = 0x10000222;


    private BaseLoadMoreView mLoadMoreView;
    private RecyclerView mRecyclerView;

    private int mLayoutResId;
    protected List<T> mData;
    private ILoadMore mILoadMore;
    private boolean mLoading = false;

    public BaseAdapter(int layoutResId, @Nullable List<T> data) {
        this.mData = data == null ? new ArrayList<T>() : data;
        if (layoutResId != 0) {
            this.mLayoutResId = layoutResId;
        }
    }

    public BaseAdapter(@Nullable List<T> data) {
        this(0, data);
    }

    public List<T> getList() {
        return mData;
    }

    public void setList(List<T> mList) {
        this.mData = mList;
    }

    @NonNull
    @Override
    public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (viewType == LOADMORE_VIEW) {
            return new BaseViewHolder(mLoadMoreView.getRootView(parent));
        } else {
            return onCreateDefViewHolder(parent, viewType);
        }
    }

    @Override
    public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {
        autoLoadMore(position);
        if (getItemViewType(position) == LOADMORE_VIEW) {
            mLoadMoreView.updateViewStatus(holder, position, mLoadMoreView.getLoadMoreStatus());
        } else {
            onBindViewHolder(holder, getItem(position));
        }
    }

    private T getItem(int position) {
        return mData.get(position);
    }

    @Override
    public int getItemCount() {
        return getDefItemCount();
    }

    public int getDefItemCount() {
        if (mLoadMoreView != null) {
            return mData.size() + 1;
        }
        return mData.size();
    }

    public void autoLoadMore(int pos) {
        if (mLoadMoreView == null) {
            return;
        }
        if (mLoadMoreView.getLoadMoreStatus() != LoadMoreStatus.Complete) {
            return;
        }
        if (!mLoading && pos >= mData.size()) {
            mLoadMoreView.setLoadMoreStatus(LoadMoreStatus.Loading);
            mLoading = true;
            mILoadMore.onLoadMore();
        }
    }

    //子类需要重写这个方法  无需重写onCreateViewHolder
    @NotNull
    protected BaseViewHolder onCreateDefViewHolder(@NotNull ViewGroup parent, int viewType) {
        return createBaseViewHolder(parent, mLayoutResId);
    }

    private BaseViewHolder createBaseViewHolder(ViewGroup parent, int mLayoutResId) {
        ViewGroup viewGroup = (ViewGroup) LayoutInflater.from(parent.getContext()).inflate(mLayoutResId, parent, false);
        return createBaseViewHolder(viewGroup);
    }

    private BaseViewHolder createBaseViewHolder(ViewGroup parent) {
        ViewGroup viewGroup = (ViewGroup) LayoutInflater.from(parent.getContext()).inflate(mLayoutResId, parent, false);
        return new BaseViewHolder(viewGroup);
    }

    /**
     *
     * 实现此方法，并使用 helper 完成 item 视图的操作
     *
     * @param holder A fully initialized helper.
     * @param item   The item that needs to be displayed.
     */
    protected abstract void onBindViewHolder(BaseViewHolder holder, T item);

    public int getItemViewType(int position) {
        if (position >= mData.size()) {
            return LOADMORE_VIEW;
        }
        return getDefItemViewType(position);
    }

    @Override
    public long getItemId(int position) {
        return super.getItemId(position);
    }

    /**
     * Override this method and return your ViewType.
     * 重写此方法，返回你的ViewType。
     */
    protected int getDefItemViewType(int position) {
        return super.getItemViewType(position);
    }

//    /**
//     * if you want to use subclass of BaseViewHolder in the adapter,
//     * you must override the method to create new ViewHolder.
//     *
//     * @param view view
//     * @return new ViewHolder
//     */
//    @SuppressWarnings("unchecked")
//    protected VH createBaseViewHolder(View view) {
//        Class temp = getClass();
//        Class z = null;
//        while (z == null && null != temp) {
//            z = getInstancedGenericKClass(temp);
//            temp = temp.getSuperclass();
//        }
//        VH vh;
//        // 泛型擦除会导致z为null
//        if (z == null) {
//            vh = (VH) new BaseViewHolder(view);
//        } else {
//            vh = createGenericKInstance(z, view);
//        }
//        return vh != null ? vh : (VH) new BaseViewHolder(view);
//    }

//    /**
//     * get generic parameter K
//     *
//     * @param z
//     * @return
//     */
//    private Class getInstancedGenericKClass(Class z) {
//        Type type = z.getGenericSuperclass();
//        if (type instanceof ParameterizedType) {
//            Type[] types = ((ParameterizedType) type).getActualTypeArguments();
//            for (Type temp : types) {
//                if (temp instanceof Class) {
//                    Class tempClass = (Class) temp;
//                    if (BaseViewHolder.class.isAssignableFrom(tempClass)) {
//                        return tempClass;
//                    }
//                } else if (temp instanceof ParameterizedType) {
//                    Type rawType = ((ParameterizedType) temp).getRawType();
//                    if (rawType instanceof Class && BaseViewHolder.class.isAssignableFrom((Class<?>) rawType)) {
//                        return (Class<?>) rawType;
//                    }
//                }
//            }
//        }
//        return null;
//    }

//    /**
//     * try to create Generic K instance
//     *
//     * @param z
//     * @param view
//     * @return
//     */
//    @SuppressWarnings("unchecked")
//    private VH createGenericKInstance(Class z, View view) {
//        try {
//            Constructor constructor;
//            // inner and unstatic class
//            if (z.isMemberClass() && !Modifier.isStatic(z.getModifiers())) {
//                constructor = z.getDeclaredConstructor(getClass(), View.class);
//                constructor.setAccessible(true);
//                return (VH) constructor.newInstance(this, view);
//            } else {
//                constructor = z.getDeclaredConstructor(View.class);
//                constructor.setAccessible(true);
//                return (VH) constructor.newInstance(view);
//            }
//        } catch (NoSuchMethodException e) {
//            e.printStackTrace();
//        } catch (IllegalAccessException e) {
//            e.printStackTrace();
//        } catch (InstantiationException e) {
//            e.printStackTrace();
//        } catch (InvocationTargetException e) {
//            e.printStackTrace();
//        }
//        return null;
//    }

    public void setLoadMoreView(BaseLoadMoreView mLoadMoreView) {
        this.mLoadMoreView = mLoadMoreView;
        this.mLoadMoreView.setLoadMoreStatus(LoadMoreStatus.Complete);
    }

    public void setILoadMore(ILoadMore iLoadMore) {
        openLoadMore(iLoadMore);
    }

    private void openLoadMore(ILoadMore iLoadMore) {
        this.mILoadMore = iLoadMore;
        mLoading = false;
    }

    public void loadMoreEnd() {
        if (mLoadMoreView == null) {
            return;
        }
        mLoading = false;
        mLoadMoreView.setLoadMoreStatus(LoadMoreStatus.End);

        mRecyclerView.post(new Runnable() {
            @Override
            public void run() {
                notifyItemChanged(mData.size());
            }
        });
    }

    /**
     * Refresh complete
     */
    public void loadMoreComplete() {
        if (mLoadMoreView == null) {
            return;
        }
        mLoading = false;
        mLoadMoreView.setLoadMoreStatus(LoadMoreStatus.Complete);
        mRecyclerView.post(new Runnable() {
            @Override
            public void run() {
                notifyItemChanged(mData.size());
            }
        });
    }

    /**
     * Refresh failed
     */
    public void loadMoreFail() {
        if (mLoadMoreView == null) {
            return;
        }
        mLoading = false;
        mLoadMoreView.setLoadMoreStatus(LoadMoreStatus.Fail);
        notifyItemChanged(mData.size());
    }

    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        mRecyclerView = recyclerView;
    }
}
